home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib25 / _dekcarc.cpp < prev    next >
Text File  |  1992-12-12  |  5KB  |  209 lines

  1. |
  2. | single floating point add/subtract routine
  3. |
  4. #ifndef    __M68881__
  5.     .text
  6.     .even
  7.     .globl    __subsf3, ___subsf3
  8.     .globl    __addsf3, ___addsf3
  9. # ifndef sfp004
  10. |
  11. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  12. | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
  13. | patched by Olaf Flebbe (flebbe@tat.physik.un-tuebingen.de)
  14. |
  15. | Revision 1.3.3 olaf 11-92 :
  16. |  + changed to get rid of rounding bits. a sticky register (d3) is
  17. |    sufficient.
  18. |
  19. | Revision 1.3.2 olaf 10-92 :
  20. |  + increased comparson by one again. (Dont understand, but it works)
  21. |  + corrected negation of rounding bits and mantissa
  22. |     >enquire now detects correct IEEE precision
  23. |     >paranoia now qualifies add/sub as correctly rounded
  24. |
  25. | Revision 1.3.1 olaf 10-92 :
  26. |  + increased comparison of exponents by one.
  27. |  + initialized sticky byte
  28. |  + corrected handling of rounding bits
  29. |  + corrected swapping of register halves
  30. |     >paranoia now detects only one (obscure) SERIOUS DEFECT.
  31. |     ** Patches need _normsf Rev 1.4.1 (or higher) **
  32. |
  33. | Revision 1.3, kub 01-90 :
  34. | added support for denormalized numbers
  35. |
  36. | Revision 1.2, kub 01-90 :
  37. | replace far shifts by swaps to gain speed (more optimization is of course
  38. | possible by doing shifts all in one intruction, but what about the rounding
  39. | bits)
  40. |
  41. | Revision 1.1, kub 12-89 :
  42. | Created single float version for 68000
  43. |
  44. | Revision 1.0:
  45. | original 8088 code from P.S.Housel for double floats
  46.  
  47. __subsf3:
  48. ___subsf3:
  49.     eorb    #0x80,sp@(8)    | reverse sign of v
  50. __addsf3:
  51. ___addsf3:
  52.     lea    sp@(4),a0    | pointer to u and v parameter
  53.     moveml    d2-d5,sp@-    | save registers
  54.     moveml    a0@,d4/d5    | d4 = v, d5 = u
  55.  
  56.     movel    d5,d0        | d0 = u.exp
  57.     swap    d0
  58.     movel    d5,d2        | d2.h = u.sign
  59.     movew    d0,d2
  60.     lsrw    #7,d0
  61.     andw    #0xff,d0    | kill sign bit (exponent is 8 bits)
  62.  
  63.     movel    d4,d1        | d1 = v.exp
  64.     swap    d1
  65.     eorw    d1,d2        | d2.l = u.sign ^ v.sign
  66.     lsrw    #7,d1
  67.     andw    #0xff,d1    | kill sign bit (exponent is 8 bits)
  68.  
  69.     andl    #0x7fffff,d5    | remove exponent from mantissa
  70.     tstw    d0        | check for zero exponent - no leading "1"
  71.     beq    0f
  72.     orl    #0x800000,d5    | restore implied leading "1"
  73.     bra    1f
  74. 0:    addw    #1,d0        | "normalize" exponent
  75. 1:
  76.     andl    #0x7fffff,d4    | remove exponent from mantissa
  77.     tstw    d1        | check for zero exponent - no leading "1"
  78.     beq    0f
  79.     orl    #0x800000,d4    | restore implied leading "1"
  80.     bra    1f
  81. 0:    addw    #1,d1        | "normalize" exponent
  82. 1:
  83.     clrl    d3        | (put initial zero rounding bits in d3)
  84.     negw    d1        | d1 = u.exp - v.exp
  85.     addw    d0,d1
  86.     beq    5f        | exponents are equal - no shifting neccessary
  87.     bgt    1f        | not equal but no exchange neccessary
  88.     exg    d4,d5        | exchange u and v
  89.     subw    d1,d0        | d0 = u.exp - (u.exp - v.exp) = v.exp
  90.     negw    d1
  91.     tstw    d2        | d2.h = u.sign ^ (u.sign ^ v.sign) = v.sign
  92.     bpl    1f
  93.     bchg    #31,d2
  94. 1:
  95.     cmpw    #26,d1        | is u so much bigger that v is not
  96.     bge    7f        | significant ?
  97. |
  98. | shift mantissa left two digits, to allow cancellation of
  99. | most significant digit, while gaining an additional digit for
  100. | rounding.
  101. |
  102.     moveql    #1,d3    
  103. 2:    addl    d5,d5
  104.     subw    #1,d0        | decrement exponent
  105.     subw    #1,d1        | done shifting altogether ?
  106.     dbeq    d3,2b        | loop if still can shift u.mant more
  107.     clrl    d3
  108.  
  109.     cmpw    #16,d1        | see if fast rotate possible
  110.     blt    4f
  111.     orw    d4,d3        | set rounding bits
  112.     clrw    d4
  113.     swap    d4
  114.     subw    #16,d1
  115.         bra     4f
  116.  
  117. 0:    moveb   d4,d2
  118.     andb    #1,d2
  119.     orb    d2,d3
  120.     lsrl    #1,d4        | shift v.mant right the rest of the way
  121. 4:    dbra    d1,0b        | loop
  122.  
  123. 5:
  124.     tstw    d2        | are the signs equal ?
  125.     bpl    6f        | yes, no negate necessary
  126.  
  127.  
  128.     tstw    d3        | negate rounding bits and v.mant
  129.     beq    9f
  130.     addql    #1,d4
  131. 9:    negl    d4
  132.  
  133. 6:
  134.     addl    d4,d5        | u.mant = u.mant + v.mant
  135.     bcs    7f        | needn not negate
  136.     tstw    d2        | opposite signs ?
  137.     bpl    7f        | do not need to negate result
  138.  
  139.     negl    d5
  140.     notl    d2        | switch sign
  141. 7:
  142.     movel    d5,d4        | move result for normalization
  143.     clrl    d1
  144.     tstl    d3
  145.     beq    8f
  146.     moveql    #-1,d1
  147. 8:    swap    d2        | put sign into d2 (exponent is in d0)
  148.     jmp    norm_sf        | leave registers on stack for norm_sf
  149.  
  150. # else    sfp004
  151.  
  152. | single precision floating point stuff for Atari-gcc using the SFP004
  153. | developed with gas
  154. |
  155. |  single floating point add/subtract routine
  156. |
  157. | M. Ritzert (mjr at dmzrzu71)
  158. |
  159. | 4.10.1990
  160. |
  161. | no NAN checking implemented since the 68881 treats this situation "correct",
  162. | i.e. according to IEEE
  163.  
  164. | addresses of the 68881 data port. This choice is fastest when much data is
  165. | transferred between the two processors.
  166.  
  167. comm =     -6
  168. resp =    -16
  169. zahl =      0
  170.  
  171. | waiting loop ...
  172. |
  173. | wait:
  174. | ww:    cmpiw    #0x8900,a0@(resp)
  175. |     beq    ww
  176. | is coded directly by
  177. |    .long    0x0c688900, 0xfff067f8
  178.  
  179. __subsf3:
  180. ___subsf3:
  181.     lea    0xfffffa50:w,a0
  182.     movew    #0x4400,a0@(comm)    | load first argument to fp0
  183.     cmpiw    #0x8900,a0@(resp)    | check
  184.     movel    a7@(4),a0@
  185.     movew    #0x4428,a0@(comm)
  186.     .long    0x0c688900, 0xfff067f8
  187.     movel    a7@(8),a0@
  188.     movew    #0x6400,a0@(comm)    | result to d0
  189.     .long    0x0c688900, 0xfff067f8
  190.     movel    a0@,d0
  191.      rts
  192.  
  193. __addsf3:
  194. ___addsf3:
  195.     lea    0xfffffa50:w,a0
  196.     movew    #0x4400,a0@(comm)        | load fp0
  197.     cmpiw    #0x8900,a0@(resp)        | got it?
  198.     movel    a7@(4),a0@            | take a from stack to FPU
  199.     movew    #0x4422,a0@(comm)        | add second arg to fp0
  200.     .long    0x0c688900, 0xfff067f8
  201.     movel    a7@(8),a0@            | move b from stack to FPU
  202.     movew    #0x6400,a0@(comm)        | result to d0
  203.     .long    0x0c688900, 0xfff067f8
  204.     movel    a0@,d0                | download result
  205.      rts
  206.  
  207. # endif    sfp004
  208. #endif    __M68881__
  209.